/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.heyma.web.licitaciones;

import com.icg.entityclassutils.DynamicEntityMap;
import com.icg.entityclassutils.EntityResult;
import com.icg.entityclassutils.Restriction;
import com.icg.entityclassutils.SimpleFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.heyma.core.dao.Dao;
import org.heyma.core.security.CustomUserDetails;
import org.heyma.core.service.IEntityServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author John
 */
@Controller
public class LicitacionesController {

    @Autowired
    IEntityServices service;
    @Autowired
    Dao dao;
    static String FILE_DIRECTORY = "D:\\reportes\\";
    //static String FILE_DIRECTORY = "/home/dismatel/documentos/licitaciones/";

    //@PreAuthorize("hasRole('ROLE_ADMIN')")
    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/formlicitacion")
    public String casos(Model model) {
        return "/licitaciones/Casos";
    }

    @RequestMapping(value = "/buscarlicitacion", method = RequestMethod.POST)
    public String casos(Model model, @RequestParam String search, @RequestParam int opcion) throws ParseException {
        if (opcion == 1) {
            //busqueda por cuce
            SimpleFilter sf = new SimpleFilter();
            sf.addValue("licitacion_cuce", search);
            sf.addANDRestriction(new Restriction("licitacion_cuce", Restriction.EQUALS));

            EntityResult lici = service.find("public", "licitacion", sf);
            List<Map<String, Object>> els = new ArrayList<Map<String, Object>>();

            for (Map<String, Object> e : lici.getListData()) {
                Map<String, Object> item = service.get("public", "licitacion", e.get("licitacion_id")).getObjectData();
                e.putAll(item);
                //agregamos el nombre de la entidad cliente
                Map<String, Object> clientes = service.get("public", "cliente", item.get("cliente_id")).getObjectData();
                e.put("cliente", clientes.get("cliente_nombre"));
                //agregamos al usuario asignado
                List<Map<String, Object>> us = dao.selectSQLMapResult("select * from asignacion where licitacion_id='" + e.get("licitacion_id") + "'");
                if (!us.isEmpty()) {
                    e.put("usuario_asignado", us.get(0).get("usuario"));
                } else {
                    e.put("usuario_asignado", ""); 
                }
                els.add(e);
            }
            model.addAttribute("resultados", els);
        }
        if (opcion == 2) {
            //busqueda por fec_registro
            System.out.println("caso 2:");
            System.out.println(search);
            Map<String, Object> params = new HashMap<String, Object>();
            DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
            params.put("desde", df.parse(search.split(",")[0]));
            params.put("hasta", df.parse(search.split(",")[1]));
            //model.addAttribute("resultados", dao.find("select * from licitacion where fec_registro between :desde and :hasta", params));

            //EntityResult er = service.find("public", "asignacion", sf);
            List<Map<String, Object>> lici = dao.find("select *, (select asignacion.usuario from asignacion where asignacion.licitacion_id = licitacion.licitacion_id) as usuario_asignado from licitacion where fec_registro between :desde and :hasta", params);
            List<Map<String, Object>> els = new ArrayList<Map<String, Object>>();
            for (Map<String, Object> e : lici) {
                Map<String, Object> item = service.get("public", "licitacion", e.get("licitacion_id")).getObjectData();
                e.putAll(item);
                //agregamos el nombre de la entidad cliente
                Map<String, Object> clientes = service.get("public", "cliente", item.get("cliente_id")).getObjectData();
                e.put("cliente", clientes.get("cliente_nombre"));
                els.add(e);
            }
            model.addAttribute("resultados", els);
        }
        if (opcion == 3) {
            //busqueda por descripcion            
            SimpleFilter sf = new SimpleFilter();
            sf.addValue("licitacion_descripcion", "%" + search + "%");
            sf.addANDRestriction(new Restriction("licitacion_descripcion", Restriction.LIKE));
            //EntityResult er = service.find("public", "licitacion", sf);            
            EntityResult lici = service.find("public", "licitacion", sf);
            List<Map<String, Object>> els = new ArrayList<Map<String, Object>>();
            for (Map<String, Object> e : lici.getListData()) {
                Map<String, Object> item = service.get("public", "licitacion", e.get("licitacion_id")).getObjectData();
                e.putAll(item);
                //agregamos el nombre de la entidad cliente
                Map<String, Object> clientes = service.get("public", "cliente", item.get("cliente_id")).getObjectData();
                e.put("cliente", clientes.get("cliente_nombre"));
                //agregamos al usuario asignado
                List<Map<String, Object>> us = dao.selectSQLMapResult("select * from asignacion where licitacion_id='" + e.get("licitacion_id") + "'");
                if (!us.isEmpty()) {
                    e.put("usuario_asignado", us.get(0).get("usuario"));
                } else {
                    e.put("usuario_asignado", ""); 
                }               
                els.add(e);
            }
            model.addAttribute("resultados", els);
            //model.addAttribute("resultados", er.getListData());
        }
        //model.addAttribute("clientes", service.find("public", "cliente", new String[] {"cliente_nombre"}).getListData());
        return "/licitaciones/Casos";
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/formbandejaentrada")
    public String bandeja(Model model) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        //Gson g = new Gson();
        //System.out.println(g.toJson(auth.getPrincipal()));
        CustomUserDetails ud = (CustomUserDetails) auth.getPrincipal();
        Collection<? extends GrantedAuthority> auths = ud.getAuthorities();
        String rol = auths.iterator().next().getAuthority();
        System.out.println(auths.iterator().next().getAuthority());
        if (rol.equals("ROLE_SUPERVISOR")) {
            model.addAttribute("licitaciones", dao.selectSQLMapResult("select *, (select cliente_nombre from cliente where cliente.cliente_id = licitacion.cliente_id) as cliente, (select usuario from asignacion where asignacion.licitacion_id = licitacion.licitacion_id) as usuario_asignado from licitacion where estado='N' or estado='P' or estado='D' order by fec_registro desc"));
        }
        if (rol.equals("ROLE_OPERADOR")) {
            SimpleFilter sf = new SimpleFilter();
            sf.addValue("usuario", auth.getName());
            sf.addANDRestriction(new Restriction("usuario", Restriction.EQUALS));
            EntityResult er = service.find("public", "asignacion", sf);
            List<Map<String, Object>> els = new ArrayList<Map<String, Object>>();
            for (Map<String, Object> e : er.getListData()) {
                Map<String, Object> item = service.get("public", "licitacion", e.get("licitacion_id")).getObjectData();
                if (item.get("estado").equals("A") || item.get("estado").equals("T")) {
                    e.putAll(item);
                    Map<String, Object> clientes = service.get("public", "cliente", item.get("cliente_id")).getObjectData();
                    e.put("cliente", clientes.get("cliente_nombre"));
                    //Map<String, Object> usuarios = service.get("public", "asignacion", item.get("licitacion_id")).getObjectData();
                    e.put("usuario_asignado", auth.getName());
                    els.add(e);
                }
            }
            model.addAttribute("licitaciones", els);
        }
        return "/licitaciones/Bandeja";
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/formregistrocaso")
    public String registrarCaso(Model model) {
        model.addAttribute("clientes", service.find("public", "cliente", new String[]{"cliente_nombre"}).getListData());
        return "/licitaciones/RegistrarCaso";
    }

    @RequestMapping(value = "/files/{dir}/{id}", method = RequestMethod.GET)
    public void getFile(@PathVariable String dir, @PathVariable Long id, HttpServletResponse response) {
        try {
            System.err.println(id);
            EntityResult en = service.get("public", "licitacion", id, new String[]{"documento_pliego", "documento_propuesta"});
            String file = "";
            if (dir.equals("licitaciones")) {
                file = "documento_pliego";
            }
            if (dir.equals("propuestas")) {
                file = "documento_propuesta";
            }
            // get your file as InputStream
            String filename = (String) en.getObjectData().get(file);
            String fullpath = FILE_DIRECTORY + filename;
            InputStream is = new FileInputStream(new File(fullpath));
            // copy it to response's OutputStream
            // get MIME type of the file
            String mimeType = URLConnection.guessContentTypeFromStream(is);
            if (mimeType == null) {
                // set to binary type if MIME mapping not found
                mimeType = "application/octet-stream";
            }
            response.setContentType(mimeType);
            // set headers for the response
            String headerKey = "Content-Disposition";
            String headerValue = String.format("attachment; filename=\"%s\"",
                    filename.substring(filename.indexOf("-") + 1));

            response.setHeader(headerKey, headerValue);

            IOUtils.copy(is, response.getOutputStream());
            response.flushBuffer();
        } catch (IOException ex) {
            //log.info("Error writing file to output stream. Filename was '" + fileName + "'");
            throw new RuntimeException("IOError writing file to output stream");
        }
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/registrarcaso", method = RequestMethod.POST)
    public String upload(Caso uploadItem) {
        try {
            //identificador de archivo
            Long identificador = System.nanoTime();
            //Nombre del archivo fisico
            String nombreArchivo = "" + identificador + "-" + uploadItem.getDocumento_pliego().getOriginalFilename() + "";
            //Copienado archivo en disco
            String path = FILE_DIRECTORY;
            File archivoFisico = new File(path + nombreArchivo);
            FileUtils.copyInputStreamToFile(uploadItem.getDocumento_pliego().getInputStream(), archivoFisico);

            Map<String, Object> textdata = new HashMap<String, Object>();
            textdata.put("licitacion_cuce", uploadItem.getLicitacion_cuce());
            textdata.put("licitacion_descripcion", uploadItem.getLicitacion_descripcion());
            textdata.put("fecha_publicacion", uploadItem.getFecha_publicacion());
            textdata.put("fecha_presentacion", uploadItem.getFecha_presentacion());
            textdata.put("hora_presentacion", uploadItem.getHora_presentacion());
            textdata.put("licitacion_monto", uploadItem.getLicitacion_monto());
            textdata.put("cliente_id", uploadItem.getCliente_id());
            textdata.put("documento_pliego", nombreArchivo);

            Map<String, String> tableMap = service.tableColumnsMap("public", "licitacion");
            Map<String, Object> insertable = DynamicEntityMap.parseInputMap(textdata, tableMap);
            //set estado
            insertable.put("estado", "N");
            //set usuario & fec_registro
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            insertable.put("usuario", auth.getName());
            insertable.put("fec_registro", new Date());

            service.persist(insertable, "licitacion");

        } catch (Exception e) {
            e.printStackTrace();
        }
        //return "/licitaciones/RegistrarCaso";
        return "redirect:/formregistrocaso";
    }

    @PreAuthorize("hasRole('ROLE_OPERADOR')")
    @RequestMapping(value = "/registrarpropuesta", method = RequestMethod.POST)
    public String registrarPropuesta(Caso uploadItem) {
        System.out.println("---------Declinacion o Aceptacion de atencion al caso----");
        System.out.println(uploadItem.getDeclinacion_descripcion());
        System.out.println(uploadItem.getEstado());
        System.out.println("-------------------------------------");

        //Si Acepta el caso se guarda la fecha de aceptacion y la empresa con la que se presentara a la licitacion
        //Si acepta el caso estado=AC ACEPTAR CASO
        if (uploadItem.getEstado().equals("T")) {
            try {
                dao.execute("update licitacion set estado='T', empresa_id=" + uploadItem.getEmpresa_id() + ", fec_aceptacion='" + new Date() + "' where licitacion_id=" + uploadItem.getLicitacion_id());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (uploadItem.getEstado().equals("A")) {
            try {
                //identificador de archivo
                Long identificador = System.nanoTime();
                //Nombre del archivo fisico
                String nombreArchivo = "" + identificador + "-" + uploadItem.getDocumento_propuesta().getOriginalFilename() + "";

                //Copienado archivo en disco
                String path = FILE_DIRECTORY;

                File archivoFisico = new File(path + nombreArchivo);
                FileUtils.copyInputStreamToFile(uploadItem.getDocumento_propuesta().getInputStream(), archivoFisico);

                dao.execute("update licitacion set estado='P', documento_propuesta='" + nombreArchivo + "', fec_propuesta='" + new Date() + "' where licitacion_id=" + uploadItem.getLicitacion_id());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            if (uploadItem.getEstado().equals("D")) {
                try {
                    dao.execute("update licitacion set estado='D', declinacion_descripcion='" + uploadItem.getDeclinacion_descripcion() + "', fec_declinacion='" + new Date() + "' where licitacion_id=" + uploadItem.getLicitacion_id());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return "redirect:/consolaasignar?id=" + uploadItem.getLicitacion_id();
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/consolaasignar")
    public String consolaAsignar(Model model, @RequestParam Long id) {
        EntityResult l = service.get("public", "licitacion", id);
        model.addAttribute("licitacion", l.getObjectData());
        model.addAttribute("cliente", service.getExistObject("public", "cliente", "cliente_id", l.getObjectData().get("cliente_id")));

        if (l.getObjectData().get("estado").equals("A")) {
            Map<String, Object> asignacion = service.getExistObject("public", "asignacion", "licitacion_id", id);
            model.addAttribute("asignacion", asignacion);
            model.addAttribute("usuario", service.getExistObject("sys", "usuario", "usuario", asignacion.get("usuario")));
            model.addAttribute("empresas", service.find("public", "empresa").getListData());
        } else {
            //users
            SimpleFilter sf = new SimpleFilter();
            sf.addValue("rol_id", 4);
            sf.addANDRestriction(new Restriction("rol_id", Restriction.EQUALS));
            model.addAttribute("usuarios", service.find("sys", "usuario", sf).getListData());
            //prioridades
            model.addAttribute("prioridades", service.find("public", "tipo_prioridad").getListData());
        }

        return "/licitaciones/ConsolaAsignar";
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/asignarcaso")
    public String asignarCaso(Model model, HttpServletRequest request) {
        try {
            // get object from request    
            Map<String, Object> insertable = service.buildPersistenObjectFromRequest("public", "asignacion", request);
            // get licitacion
            EntityResult l = service.get("public", "licitacion", insertable.get("licitacion_id"));
            // persist asignacion
            insertable.put("fecha_asignacion", new Date());
            service.persist(insertable, "public", "asignacion");
            // update licitacion estate
            l.getObjectData().put("estado", "A");
            service.persist(l.getObjectData(), "public", "licitacion");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:/consolaasignar?id=" + request.getParameter("licitacion_id");
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/eliminarasignacion")
    public String eliminarAsignacion(Model model, @RequestParam Long id) {
        try {
            // get asignacion
            EntityResult a = service.get("public", "asignacion", id);
            // get licitacion
            EntityResult l = service.get("public", "licitacion", a.getObjectData().get("licitacion_id"));
            // delete asignacion
            service.deleteObject("public", "asignacion", id);
            // update licitacion estate
            l.getObjectData().put("estado", "N");
            service.persist(l.getObjectData(), "public", "licitacion");
            return "redirect:/consolaasignar?id=" + a.getObjectData().get("licitacion_id");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/archivarcaso")
    public String archivarCaso(Model model, @RequestParam Long id) {
        try {
            // get licitacion
            EntityResult l = service.get("public", "licitacion", id);
            // update licitacion estate
            l.getObjectData().put("estado", "L");
            service.persist(l.getObjectData(), "public", "licitacion");
            return "redirect:/consolaasignar?id=" + id;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(value = "/reasignarcaso")
    public String reasignarCaso(Model model, @RequestParam Long id) {
        try {
            // get licitacion
            EntityResult l = service.get("public", "licitacion", id);
            //get asignacion
            EntityResult a = service.get("public", "asignacion", l.getObjectData().get("licitacion_id"));
            System.out.println("------Eliminamos la asignacion para reasignar -------");
            // delete asignacion
            dao.execute("delete from asignacion where licitacion_id=" + id);

            //update licitacion estate
            l.getObjectData().put("estado", "N");
            l.getObjectData().put("empresa_id", null);
            l.getObjectData().put("declinacion_descripcion", null);
            l.getObjectData().put("fec_declinacion", null);
            l.getObjectData().put("fec_aceptacion", null);
            service.persist(l.getObjectData(), "public", "licitacion");
            return "redirect:/consolaasignar?id=" + id;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
